/**
 * @Author: zxc
 * @Date: 2020-11-11 09:33:58
 * @func 迭代器模式
 */
// :迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素，而又不需要暴露该对象 5 的内部表示

/**
 * @Author: zxc
 * @Date: 2020-11-11 09:46:19
 * @func 自定义简易迭代器
 */
// let each = function (ary, callback) {
//   for (var i = 0, len = ary.length; i < len; i++) {
//     callback.call(null, i, ary[i])
//   }
// }
// each([1, 2, 3], function (i, n) {
//   alert([i, n])
// })

/**
 * @Author: zxc
 * @Date: 2020-11-11 09:46:36
 * @func 内部迭代器=>完全接手整个迭代过程，仅需要外部一次调用
 */
//  实现一个简单的需求，上面的也算内部内部迭代器

// let each = function (ary, callback) {
//   for (var i = 0, len = ary.length; i < len; i++) {
//     callback.call(null, i, ary[i])
//   }
// }
// const compare = function (ary1, ary2) {
//   if (ary1.length !== ary2.length) throw new Error("ary1 与 ary2 不相等")
//   each(ary1, function (i, n) {
//     if (ary2[i] !== n) throw new Error("ary1 与 ary2 不相等")
//   })
//   alert("相等")
// }

// compare([1, 2, 4], [1, 2, 4])

/**
 * @Author: zxc
 * @Date: 2020-11-11 10:01:02
 * @func 外部迭代器：必须显式地请求迭代下一个元素
 */
// let Iterator = function (obj) {
//   let current = 0
//   let next = function () {
//     current += 1
//   }
//   let isDone = function () {
//     return current >= obj.length
//   }
//   let getCurrItem = function () {
//     return obj[current]
//   }
//   return {
//     next,
//     isDone,
//     getCurrItem
//   }
// }

// let compare = function (iterator1, iterator2) {
//   while (!iterator1.isDone() && !iterator2.isDone()) {
//     if (iterator1.getCurrItem() !== iterator2.getCurrItem()) {
//       throw new Error("不等")
//     }
//     iterator1.next()
//     iterator2.next()
//   }
//   alert("等")
// }
// compare(Iterator([1, 2, 4]), Iterator([1, 2, 4]))

/**
 * @Author: zxc
 * @Date: 2020-11-11 10:36:08
 * @func 现代js中的迭代器协议
 */
let authors = {
  allAuthors: {
    fiction: ["Agatha Christie", "J. K. Rowling", "Dr. Seuss"],
    scienceFiction: [
      "Neal Stephenson",
      "Arthur Clarke",
      "Isaac Asimov",
      "Robert Heinlein"
    ],
    fantasy: ["J. R. R. Tolkien", "J. K. Rowling", "Terry Pratchett"]
  }
}
authors[Symbol.iterator] = function () {
  let allAuthors = this.allAuthors
  let keys = Reflect.ownKeys(allAuthors)
  let values = []
  return {
    next() {
      if (!values.length) {
        if (keys.length) {
          values = allAuthors[keys[0]]
          keys.shift()
        }
      }
      return {
        done: !values.length,
        value: values.shift()
      }
    }
  }
}
for (let value of authors) {
  console.log(`${value}`)
}
